﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace WorldEvolution
{  
    

    public class Zone : Object
    {
        static Dictionary<ulong, Zone> mZoneDict = new Dictionary<ulong, Zone>();
        public static  Dictionary<ulong, Zone> Zones { get { return mZoneDict; } }

        public static Zone Create()
        {
            var z = new Zone();
            z.OnCreate();
            return z;
            
        }

        public void Evolute()
        {
            foreach (var list in mCellsRT)
                foreach (var c in list)
                    c.Evolute();

            foreach (var list in mCellsLT)
                foreach (var c in list)
                    c.Evolute();

            foreach (var list in mCellsRB)
                foreach (var c in list)
                    c.Evolute();

            foreach (var list in mCellsLB)
                foreach (var c in list)
                    c.Evolute();
        }

        public void Load(DBData.ZoneData data)
        {
            mZoneDict[data.ID] = this;
        }


        protected void OnCreate()
        {
            var ranEle = Util.Rand.Next(WorldDefine.ZoneMinElementCount, WorldDefine.ZoneMaxElementCount);

            mElements = new byte[ranEle*ElementData.StructSize];
            Util.Rand.NextBytes(mElements);

            var cell = CreateNewCell(0, 0);
        }

        public Cell GetCell(int x,int y)
        {
            if(x>=0 && y>=0 )
            {//原点 0,0
                if (mCellsRT.Count <= x)
                    return null;
                if (mCellsRT[x].Count <= y)
                    return null;
                return mCellsRT[x][y];
            }
            else if( x < 0 && y >= 0)
            {//原点 -1，0
                int _x = -x - 1;

                if (mCellsLT.Count <= _x)
                    return null;
                if (mCellsLT[x].Count <= y)
                    return null;
                return mCellsLT[_x][y];
            }
            else if (x < 0 && y < 0)
            {//原点 -1,-1
                int _x = -x - 1;
                int _y = -y - 1;
                if (mCellsLB.Count <= _x)
                    return null;
                if (mCellsLB[-x].Count <= _y)
                    return null;
                return mCellsLB[_x][_y];

            }
            else //if (x >= 0 && y < 0)
            {//原点 0，-1
                int _y = -y - 1;
                if (mCellsRB.Count <= x)
                    return null;
                if (mCellsRB[x].Count <= _y)
                    return null;
                return mCellsRB[x][_y];
            }            
        }

        Cell CreateNewCell(Cell from, EDirection dir)
        {
            Cell cell = null;
            switch (dir)
            {
                case EDirection.Top:                    
                    cell = CreateNewCell(from.x, from.y + 1);
                    break;
                case EDirection.Bottom:
                    cell = CreateNewCell(from.x, from.y - 1);
                    break;
                case EDirection.Left:
                    cell = CreateNewCell(from.x - 1, from.y);
                    break;
                case EDirection.Right:
                    cell = CreateNewCell(from.x + 1, from.y);
                    break;
                case EDirection.LeftTop:
                    cell = CreateNewCell(from.x - 1, from.y + 1);
                    break;
                case EDirection.LeftBottom:
                    cell = CreateNewCell(from.x - 1, from.y - 1);
                    break;
                case EDirection.RightTop:
                    cell = CreateNewCell(from.x + 1, from.y + 1);
                    break;
                case EDirection.RightBottom:
                    cell = CreateNewCell(from.x + 1, from.y - 1);
                    break;
                default:
                    return null;
            }

            return cell;
        }

        Cell CreateNewCell(int x,int y)
        {
            if (mCurPos < 0 || mCurPos >= mElements.Length - ElementData.StructSize)
                return null;

            Cell cell = Cell.Create(x, y);
            _FillCellDir(cell);
            _AddToCells(cell,x,y);

            cell.FillElements(mElements, mCurPos);
            mCurPos += ElementData.StructSize;


            if(mCurPos >= mElements.Length - ElementData.StructSize)
            {
                mCurPos = -1;
                mElements = null;
            }

            return cell;
        }

        void _FillCellDir(Cell cell)
        {
            cell.Top = GetCell(cell.x, cell.y + 1);
            if (cell.Top != null)
                cell.Top.Bottom = cell;                
            cell.Bottom = GetCell(cell.x, cell.y - 1);
            if (cell.Bottom != null)
                cell.Bottom.Top = cell;
            cell.Left = GetCell(cell.x - 1, cell.y );
            if (cell.Left != null)
                cell.Left.Right = cell;
            cell.Right = GetCell(cell.x + 1, cell.y );
            if (cell.Right != null)
                cell.Right.Left = cell;
        }

        void _AddToCells(Cell cell,int x,int y)
        {
            if (x >= 0 && y >= 0)
            {//原点 0,0
                while (mCellsRT.Count <= x)
                    mCellsRT.Add(new List<Cell>());
                while (mCellsRT[x].Count <= y)
                    mCellsRT[x].Add(null);

                mCellsRT[x][y] = cell;
            }
            else if (x < 0 && y >= 0)
            {//原点 -1，0
                int _x = -x - 1;
                while (mCellsLT.Count <= _x)
                    mCellsLT.Add(new List<Cell>());
                while (mCellsLT[_x].Count <= y)
                    mCellsLT[_x].Add(null);
                mCellsLT[_x][y] = cell;
            }
            else if (x < 0 && y < 0)
            {//原点 -1,-1
                int _x = -x - 1;
                int _y = -y - 1;
                while (mCellsLB.Count <= _x)
                    mCellsLB.Add(new List<Cell>());
                while (mCellsLB[_x].Count <= _y)
                    mCellsLB[_x].Add(null);
                mCellsLB[_x][_y] = cell;
            }
            else //if (x >= 0 && y < 0)
            {//原点 0，-1
                int _y = -y - 1;
                while (mCellsRB.Count <= x)
                    mCellsRB.Add(new List<Cell>());
                while (mCellsRB[x].Count <= _y)
                    mCellsRB[x].Add(null);
                mCellsRB[x][_y] = cell;
            }
        }

        List<List<Cell>> mCellsRT = new List<List<Cell>>(); //右上坐标系 ,原点 0,0
        List<List<Cell>> mCellsLT = new List<List<Cell>>(); //左上坐标系 ,原点 -1，0
        List<List<Cell>> mCellsLB = new List<List<Cell>>(); //左下坐标系 ,原点 -1,-1
        List<List<Cell>> mCellsRB = new List<List<Cell>>(); //右下坐标系 ,原点 0，-1

        byte[] mElements;
        int mCurPos = 0;
        DBData.ZoneData mData;
    }
}
